use std::path::PathBuf;
use std::str::FromStr;

use anyhow::anyhow;
use log4rs::append::console::ConsoleAppender;
use log4rs::append::rolling_file::policy::compound::CompoundPolicy;
use log4rs::append::rolling_file::policy::compound::roll::fixed_window::FixedWindowRoller;
use log4rs::append::rolling_file::policy::compound::trigger::size::SizeTrigger;
use log4rs::Config;
use log4rs::config::{Appender, Root};
use log4rs::encode::pattern::PatternEncoder;
use log4rs::filter::threshold::ThresholdFilter;
use log::LevelFilter;

use crate::common::CommResult;

pub fn init(log_path: String, log_level: String) -> CommResult<()> {
    // println!("日志配置:path>{} level>{}", &log_path, &log_level);
    let level = LevelFilter::from_str(log_level.as_str()).unwrap_or(LevelFilter::Info);
    // Create a policy to use with the file logging
    let trigger = SizeTrigger::new(10 << 10 << 10);
    let gzip_path = PathBuf::from(&log_path).join("info-{}.log");
    let roller = FixedWindowRoller::builder()
        .build(gzip_path.to_str().unwrap_or("nozipname-{}.log"), 2)?;
    let policy = CompoundPolicy::new(Box::new(trigger), Box::new(roller));
    // Logging to log file. (with rolling)
    let logfile = log4rs::append::rolling_file::RollingFileAppender::builder()
        .encoder(Box::new(PatternEncoder::new(
            "{d(%Y-%m-%d %H:%M:%S%.3f)} {h({l}):<5.5} [{I:<5}] {f} {m}{n}")))
        .build(PathBuf::from(&log_path).join("info.log").to_str()
                   .unwrap_or("nofname.log"), Box::new(policy))
        .map_err(|e| anyhow!(e))?;
    let stdout = ConsoleAppender::builder()
        .encoder(Box::new(PatternEncoder::new("{d(%H:%M:%S%.3f)} {h({l}):<5.5} {f}:{L} {m}{n}")))
        .build();

    // Log Trace level output to file where trace is the default level
    // and the programmatically specified level to stderr.
    let config = Config::builder()
        .appender(Appender::builder().build("logfile", Box::new(logfile)))
        .appender(
            Appender::builder()
                .filter(Box::new(ThresholdFilter::new(LevelFilter::Info)))
                .build("stdout", Box::new(stdout)),
        )
        .build(
            Root::builder()
                .appender("logfile")
                .appender("stdout")
                .build(level),
        )?;

    let _handle = log4rs::init_config(config)?;
    return Ok(());
}